﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI;
using System.Reflection;
using System.Web.UI.WebControls;
using Component.CConvert;
using System.Web.UI.HtmlControls;

namespace System.Web
{
    public class ZBinder
    {
        public static T BindControlsToModel<T>(T model, Control container)
        {
            if (model == null)
                return default(T);

            Type objType = model.GetType();
            PropertyInfo[] objProperties = objType.GetProperties();

            foreach (PropertyInfo modelProperty in objProperties)
            {
                string key = string.Format("{0}_{1}", objType.Name, modelProperty.Name);
                Control control = container.FindControl(key);
                if (control == null) continue;

                if (control is IAttributeAccessor)
                {
                    IAttributeAccessor htmlControl = (IAttributeAccessor)control;
                    string sIsLongDate = htmlControl.GetAttribute("update");
                    if (sIsLongDate == "false") continue;

                }

                if (control is ListControl)
                {
                    ListControl listControl = (ListControl)control;
                    if (listControl.SelectedItem != null)
                        FindAndGetControlProperty<T>(model, modelProperty, listControl.SelectedItem.Value);
                }
                else
                {
                    bool success = false;
                    success = FindAndGetControlProperty<T>(model, modelProperty, control, "Checked");

                    if (!success)
                        success = FindAndGetControlProperty<T>(model, modelProperty, control, "Value");

                    if (!success)
                        success = FindAndGetControlProperty<T>(model, modelProperty, control, "Text");
                }
            }
            return model;
        }

        public static void BindModelToControls<T>(T model, Control container)
        {
            if (model == null) return;

            Type modelType = model.GetType();
            PropertyInfo[] modelProperties = modelType.GetProperties(BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public);

            foreach (PropertyInfo modelProperty in modelProperties)
            {
                string key = string.Format("{0}_{1}", modelType.Name, modelProperty.Name);
                Control control = container.FindControl(key);
                if (control == null) continue;

                if (control is ListControl)
                {
                    ListControl listControl = (ListControl)control;
                    listControl.SelectedIndex = -1;
                    Object obj = modelProperty.GetValue(model, null);
                    string propertyValue = "";
                    if (obj != null)
                        propertyValue = modelProperty.GetValue(model, null).ToString();
                    ListItem listItem = listControl.Items.FindByValue(propertyValue);
                    if (listItem != null)
                    {
                        listItem.Selected = true;
                    }
                }
                else
                {
                    bool success = false;
                    success = FindAndSetControlProperty<T>(model, modelProperty, control, "Checked");

                    if (!success)
                        success = FindAndSetControlProperty<T>(model, modelProperty, control, "Value");

                    if (!success)
                        success = FindAndSetControlProperty<T>(model, modelProperty, control, "Text");

                }
            }
        }

        private static bool FindAndSetControlProperty<T>(T model, PropertyInfo modelProperty, Control control, string propertyName)
        {
            PropertyInfo info = control.GetType().GetProperty(propertyName);
            if (info == null)
                return false;
            try
            {
                object resultValue = Convert.ChangeType(modelProperty.GetValue(model, null), info.PropertyType);
                if (modelProperty.PropertyType == typeof(Nullable<DateTime>))
                {
                    if (resultValue != null)
                    {
                        bool IsLongDate = false;

                        if (control is IAttributeAccessor)
                        {
                            IAttributeAccessor htmlControl = (IAttributeAccessor)control;
                            string sIsLongDate = htmlControl.GetAttribute("IsLongDate");
                            if (!string.IsNullOrEmpty(sIsLongDate) && sIsLongDate == "true")
                            { IsLongDate = true; }
                        }

                        if (!IsLongDate)
                            resultValue = Convert.ToDateTime(resultValue).ToShortDateString();
                    }

                }
                info.SetValue(control, resultValue, null);
                return true;
            }
            catch
            {
                return false;
            }
        }

        private static bool FindAndGetControlProperty<T>(T model, PropertyInfo modelProperty, Control control, string propertyName)
        {
            PropertyInfo info = control.GetType().GetProperty(propertyName);

            if (info == null)
                return false;

            //try
            //{
                object data = info.GetValue(control, null);
                FindAndGetControlProperty<T>(model, modelProperty, data);
                return true;
            //}
            //catch( Exception e )
            //{
            //    MyException ex = new MyException(e.Message, "BaseModel OnPropertyChanging(ModifyInfo info);");
            //    ex.Tag = info;
            //    throw ex;
            // }
        }

        private static void FindAndGetControlProperty<T>(T model, PropertyInfo modelProperty, object data)
        {
            Type proType = modelProperty.PropertyType;

            if (proType.Name.Contains("Nullable"))
            {
                if (proType == typeof(Nullable<int>))
                {
                    int? nullAbleData = IntHelper.ToInt(data, null);
                    modelProperty.SetValue(model, nullAbleData, null);
                }
                if (proType == typeof(Nullable<short>))
                {
                    short? nullAbleData = ShortHelper.ToShort(data, null);
                    modelProperty.SetValue(model, nullAbleData, null);
                }
                if (proType == typeof(Nullable<decimal>))
                {
                    decimal? nullAbleData = DecimalHelper.ToDecimal(data, null);
                    modelProperty.SetValue(model, nullAbleData, null);
                }
                if (proType == typeof(Nullable<double>))
                {
                    double? nullAbleData = DoubleHelper.ToDouble(data, null);
                    modelProperty.SetValue(model, nullAbleData, null);
                }
                if (proType == typeof(Nullable<bool>))
                {
                    bool? nullAbleData = BoolHelper.ToBool(data, null);
                    modelProperty.SetValue(model, nullAbleData, null);
                }
                if (proType == typeof(Nullable<DateTime>))
                {
                    DateTime? nullAbleData = DateHelper.ToDate(data, null);
                    modelProperty.SetValue(model, nullAbleData, null);

                }
            }
            else
            {
                modelProperty.SetValue(model, Convert.ChangeType(data, proType, null), null);

            }
        }

        public static void BindListControl<T>(ListControl listControl, string textField, string valueField, string filter)
            where T : BaseModel, new()
        {
            BindListControl<T>(listControl, textField, valueField, filter, "");
        }

        public static void BindListControl<T>(ListControl listControl, string textField, string valueField, string filter, string sort)
           where T : BaseModel, new()
        {
            BaseBLL<T> bll = new BaseBLL<T>();
            List<T> list = bll.GetList("", filter, sort, null);
            listControl.DataSource = list;
            listControl.DataTextField = textField;
            listControl.DataValueField = valueField;
            listControl.DataBind();
            bll.Dispose();
        }

        public static void BindListControl<T>(ListControl listControl, string textField, string valueField)
            where T : BaseModel, new()
        {
            BindListControl<T>(listControl, textField, valueField, "1=1");
        }

        public static void BindListControl<T>(string configName, ListControl listControl, string textField, string valueField, string filter)
           where T : BaseModel, new()
        {
            BaseBLL<T> bll = new BaseBLL<T>();
            if (!string.IsNullOrEmpty(configName))
                bll.ConfigName = configName;
            List<T> list = bll.GetList("", filter, "", null);
            listControl.DataSource = list;
            listControl.DataTextField = textField;
            listControl.DataValueField = valueField;
            listControl.DataBind();
            bll.Dispose();
        }

        public static void BindListControl<T>(string configName, ListControl listControl, string textField, string valueField)
            where T : BaseModel, new()
        {
            BindListControl<T>(configName, listControl, textField, valueField, "1=1");
        }

        public static void BindListControl<T>(ListControl listControl, string textField, string valueField, string filter, string configName, bool ifAddEmpty)
          where T : BaseModel, new()
        {
            BaseBLL<T> bll = new BaseBLL<T>();
            if (!string.IsNullOrEmpty(configName))
                bll.ConfigName = configName;
            List<T> list = bll.GetList("", filter, "", null);
            listControl.DataSource = list;
            listControl.DataTextField = textField;
            listControl.DataValueField = valueField;
            listControl.DataBind();
            bll.Dispose();
            if (ifAddEmpty)
            {
                listControl.Items.Insert(0, new ListItem("--请选择--", ""));
            }
        }

        public static void BindListControl<T>(ListControl listControl, string textField, string valueField, bool ifAddEmpty)
         where T : BaseModel, new()
        {
            BindListControl<T>(listControl, textField, valueField, "1=1", "", ifAddEmpty);
        }


        public static void BindControl(Control control, string value)
        {
            if (control is ListControl)
            {
                ListControl listControl = (ListControl)control;
                listControl.SelectedIndex = -1;
                ListItem listItem = listControl.Items.FindByValue(value);
                if (listItem != null)
                {
                    listItem.Selected = true;
                }
            }
            else
            {
                bool success = false;
                success = FindAndSetControlProperty(control, value, "Checked");
                if (!success)
                    success = FindAndSetControlProperty(control, value, "Value");
                if (!success)
                    success = FindAndSetControlProperty(control, value, "Text");
            }
        }

        public static bool FindAndSetControlProperty(Control control, string value, string propertyName)
        {
            PropertyInfo info = control.GetType().GetProperty(propertyName);
            if (info == null)
                return false;
            try
            {
                info.SetValue(control, value, null);
                return true;
            }
            catch
            {
                return false;
            }
        }
        public static object GetControlValue(Control control)
        {
            object result = null;
            if (control is ListControl)
            {
                ListControl listControl = (ListControl)control;
                if (listControl.SelectedItem != null)
                    return listControl.SelectedValue;
            }
            else
            {
                bool success = false;
                success = FindAndGetControlProperty(control, "Checked", out result);
                if (!success)
                    success = FindAndGetControlProperty(control, "Value", out result);
                if (!success)
                    success = FindAndGetControlProperty(control, "Text", out result);
            }
            return result;
        }
        private static bool FindAndGetControlProperty(Control control, string propertyName, out object value)
        {
            PropertyInfo info = control.GetType().GetProperty(propertyName);
            value = null;
            if (info == null)
                return false;
            try
            {
                object data = info.GetValue(control, null);
                value = data;
                return true;
            }
            catch
            {
                return false;
            }
        }
    }
}
